package com.sinodata.bsm.inmp.util;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.StringWriter;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;

import org.apache.log4j.Logger;

/**
 * 
 * <p>
 * Description: 
 * </p>
 *
 * @author liulibo
 * @version 1.0

 * <p>
 * History: 
 *
 * Date                     Author         Version     Description
 * ---------------------------------------------------------------------------------
 * 2012-12-26 AM 10:31:05   liulibo        1.0         To create
 * </p>
 *
 * @since 
 * @see
 */
public class SocketUtil {
    private final static Logger logger = Logger.getLogger(SocketUtil.class);

    //
    //    private static final int K = 1024;

    //    private static final int MAX_SIZE = K * K;

    public static byte[] getBuffer() {
        return buffer;
    }

    public static void setBuffer(byte[] buffer) {
        SocketUtil.buffer = buffer;
    }

    private static byte[] buffer;

    private SocketUtil() {
    }

    /**
     * 创建socket连接
     *
     * @param host
     * @param port
     * @return
     * @throws java.io.IOException
     */
    public static Socket createSocket(String host, int port) throws java.io.IOException, java.net.SocketTimeoutException, java.nio.channels.IllegalBlockingModeException, java.lang.IllegalArgumentException {
        Socket socket = new Socket();
        SocketAddress addr = new InetSocketAddress(host, port);
        socket.connect(addr, 10000);
        return socket;
    }

    /**
     * read data from socket and reture the byte[] result
     *
     * @param socket
     * @return
     * @throws IOException
     */
    public static byte[] getByteArrFromSocket(Socket socket) throws IOException {
        try {
            BufferedInputStream in = new BufferedInputStream(socket.getInputStream()); // 结束时不要关闭，否则会关闭Socket
            byte[] lengthBytes = new byte[10];
            int readLen = in.read(lengthBytes);
            StringBuffer sb = new StringBuffer();
            if (readLen != -1) {
                for (int i = 0; i < readLen; i++) {
                    sb.append((char) lengthBytes[i]);
                }
            }

            int dataLength = Integer.parseInt(sb.toString());
            byte[] content = new byte[dataLength];
            int totalReadCnt = in.read(content);
            while (totalReadCnt < dataLength) {
                int readCnt = in.read(content, totalReadCnt, dataLength - totalReadCnt);
                if (readCnt < 0) {
                    break;
                }
                totalReadCnt += readCnt;
            }
            if (totalReadCnt != dataLength) {
                logger.error("Read length not equal set length of packet:" + totalReadCnt + "," + dataLength);
                throw new IOException("Read length not equal set length of packet:" + totalReadCnt + "," + dataLength);
            }
            return content;
        } catch (Throwable t) {
            logger.error(t);
            throw new IOException(t.getMessage());
        }
    }

    /**
     * 将byte[]数据发送到socket中
     *
     * @param socket
     * @param bytes
     * @throws IOException
     */
    public static void setByteArrToSocket(Socket socket, byte[] bytes) throws IOException {
        DataOutputStream out = new DataOutputStream(socket.getOutputStream());
        byte[] lengthBytes = fill(bytes.length + "", '0', 10).getBytes();
        out.write(lengthBytes);
        out.write(bytes);
    }

    /**
     * 一次write整个包,将byte[]数据发送到socket中
     *
     * @param socket
     * @param bytes
     * @throws IOException
     */
    public static void writeByteArrToSocket(Socket socket, byte[] bytes) throws IOException {
        DataOutputStream out = new DataOutputStream(socket.getOutputStream());
        byte[] lengthBytes = fill(bytes.length + "", '0', 10).getBytes();
        String totalMsg = new String(lengthBytes) + new String(bytes);
        out.write(totalMsg.getBytes());
    }

    public static void closeSocket(Socket socket) {
        if (socket != null) {
            InputStream is = null;
            OutputStream os = null;
            try {
                is = socket.getInputStream();
            } catch (Throwable t) {
                logger.error(t);
            }
            try {
                os = socket.getOutputStream();
            } catch (Throwable t) {
                logger.error(t);
            }

            if (is != null) {
                try {
                    is.close();
                } catch (Throwable t) {
                    logger.error(t);
                }
            }
            if (os != null) {
                try {
                    os.close();
                } catch (Throwable t) {
                    logger.error(t);
                }
            }

            try {
                socket.close();
            } catch (IOException e) {
                logger.error(e);
            }
        }
    }

    private static String fill(String str, char fillChar, int length) {
        if (str == null || str.length() >= length) {
            return str;
        } else {
            StringBuffer buffer = new StringBuffer(str);
            while (buffer.length() < length) {
                buffer.insert(0, fillChar);
            }
            return buffer.toString();
        }
    }

    /*
     * 2007-7-31
     */
    public static void writeObject(Socket socket, Object request) throws Exception {
        ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
        oos.writeObject(request);
        oos.flush();
    }

    public static Object readObject(Socket socket) throws Exception {
        Object result = null;
        ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
        result = ois.readObject();
        return result;
    }

    public static void closeWait(Socket socket) {
        try {
            while (socket.getInputStream().read() != -1) {
            }
        } catch (Exception e) {
            logger.error(e);
        } finally {
            SocketUtil.closeSocket(socket);
        }
    }

    public static void main(String args[]) {
        InetSocketAddress endpoint = new InetSocketAddress("localhost", 5060);

        Socket socket = null;
        OutputStream out = null;
        InputStream in = null;
        try {
            socket = new Socket();
            //设置发送逗留时间2秒  
            socket.setSoLinger(true, 2);
            //设置InputStream上调用 read()阻塞超时时间2秒  
            socket.setSoTimeout(2000);
            //设置socket发包缓冲为32k；  
            socket.setSendBufferSize(32 * 1024);
            //设置socket底层接收缓冲为32k  
            socket.setReceiveBufferSize(32 * 1024);
            //关闭Nagle算法.立即发包  
            socket.setTcpNoDelay(true);
            //连接服务器  
            socket.connect(endpoint);
            //获取输出输入流  
            out = socket.getOutputStream();
            in = socket.getInputStream();
            //输出请求            
            out.write("pwd".getBytes());
            out.flush();
            //接收应答  
            BufferedReader br = new BufferedReader(new InputStreamReader(in), 4096);
            StringWriter received = new StringWriter(4096);
            char[] charBuf = new char[4096];
            int size = 0;
            char lastChar = 0;
            String line = "";
            while ((line = br.readLine()) != null) {
                System.out.println(line);
            }


        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (out != null) {
                try {
                    out.close();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
            if (in != null) {
                try {
                    in.close();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
            if (socket != null) {
                try {
                    socket.close();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        }

    }
}
